package socket;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

import service.MessageHandler;
import service.ServerCommand;

public class ClientSocket {
        private ObjectOutputStream out;
        private ObjectInputStream in;
        private BufferedReader input;
        
        public static void main(final String args[]) {
                ClientSocket client = new ClientSocket();
                client.startClient();
        }
        
        public void startClient() {
                Socket requestSocket = null;
                boolean inChat;
                final int port = 2005;
                final String hostname = "localhost";
                
                try {
                        requestSocket = new Socket(hostname, port); //[ek] TODO move hostname and port to global constants
                        System.out.println("Connected to localhost in port " + port);
                        
                        in = new ObjectInputStream(requestSocket.getInputStream()); //[ek] TODO is this variable really needed?
                        out = new ObjectOutputStream(requestSocket.getOutputStream());
                        input = new BufferedReader(new InputStreamReader(System.in));
                        
                        MessageHandler messageHandler = new MessageHandler(out,in);
                        
                        inChat = authentificationRequest(messageHandler);
                        if (inChat == false)
                        	return;
                    
                        
                        MessageSenderThread messageThread = new MessageSenderThread(messageHandler);
                        //if (inChat)
                               // messageThread.start();
                        
                        
                        while (inChat) {
                                try {
                                        String incomingMessage = messageHandler.readMessage();
                                        System.out.println(incomingMessage);
                                        if (incomingMessage.equals(ServerCommand.goodbye.toString())) {
                                                messageThread.interrupt();
                                                inChat = false;
                                        }
                                        
                                } catch (IOException e) {
                                        inChat = false;
                                        System.out.println("Connection with server is lost"); //[ek] TODO use more user-friendly messages
                                } 
                        } 
                        
                } catch (UnknownHostException unknownHost) {
                        System.out.println("You are trying to connect to an unknown host!");
                } catch (IOException ioException) {
                        System.out.println("Connection with server is lost");
                } finally {
                        try {
                                //[ek] TODO possible NPE here
                                if (in != null)
                                        in.close();
                                
                                if (out != null)
                                        out.close();
                        
                                //[ek] TODO it closed automatically when in.close()
                        } catch (IOException ioException) {
                                System.out.println("Connection with server is lost");
                        }
                }
        }
        
        //[ek] TODO please use verbs in method names
        // this is not authentification itself, here client just sends to server his login & password
        private boolean authentificationRequest(MessageHandler messageHandler) throws IOException {
                String message = messageHandler.readMessage();
                System.out.println(message);
                String command;
                boolean tryAuthentication = true;
                
                while(tryAuthentication) {
                        //[ek] TODO use your own protocol but not with strings as you're doing. It'll be difficult to change messages if needed.
                        //[ek] TODO you have commands!
                        if (message.equals(ServerCommand.auth.toString())) {
                                System.out.print("login: ");
                                messageHandler.sendMessage(input.readLine());
                                System.out.print("password: "); 
                                messageHandler.sendMessage(input.readLine());
                        }//[ek] TODO and where is auth?
                        
                        message = messageHandler.readMessage();
                        System.out.println(message);
                        
                        //[ek] TODO it's not authentication now!
                        ServerCommand serverCommand = ServerCommand.getType(message);
               
                        switch (serverCommand) {
                        case ok:
                                tryAuthentication = false;
                                
                                break;
                                
                        case tryAgain:
                                command = input.readLine();
                                messageHandler.sendMessage(command);
                                
                                message = messageHandler.readMessage();
                                System.out.println(message);
                                
                                if (command.equals("n"))
                                        return false;
                                
                                break;
                        }
                }
                return true;
        }
}